package com.taobao.demo.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.taobao.demo.user.dto.PasswordDTO;
import com.taobao.demo.user.dto.UserInfoDTO;
import com.taobao.demo.user.dto.UserLoginDTO;
import com.taobao.demo.user.dto.UserRegisterDTO;
import com.taobao.demo.user.entity.LoginLog;
import com.taobao.demo.user.entity.User;
import com.taobao.demo.user.entity.UserBehavior;
import com.taobao.demo.user.exception.UserAuthException;
import com.taobao.demo.user.mapper.UserBehaviorMapper;
import com.taobao.demo.user.mapper.UserMapper;
import com.taobao.demo.user.service.IUserService;
import com.taobao.demo.user.utils.JwtUtil;
import com.taobao.demo.user.mapper.LoginLogMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 类描述：
 * 
 * @author xhy
 * date 2025/10/16 18:00
 * @version 1.0.0
 */
@Service
public class UserserviceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Resource // 或 @Autowired
    private JwtUtil jwtUtil;
    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    @Resource
    private LoginLogMapper loginLogMapper; // 注入日志Mapper
    @Resource
    private UserBehaviorMapper userBehaviorMapper;
    @Override
    public boolean register(UserRegisterDTO registerDTO) {
        User existUser;
        try {
            // 仅将“查询用户”的操作放在 try 块（可能抛出数据库异常）
            existUser = getByUsername(registerDTO.getUsername());
        } catch (Exception e) {
            // 这里只处理“获取用户信息失败”的系统异常（如数据库连接问题）
            throw new UserAuthException("获取用户信息失败，请重试！" + e.getMessage());
        }

        // 2. 用户名已存在的判断，放在 try 块外（避免被误捕获）
        if (existUser != null) {
            // 直接抛出业务异常，不会被上面的 catch 捕获
            throw new UserAuthException("用户名已存在");
        }

        // 3. 密码加密 + 保存用户（后续逻辑不变）
        String encryptedPwd = passwordEncoder.encode(registerDTO.getPassword());
        User user = new User();
        BeanUtils.copyProperties(registerDTO, user);
        user.setPassword(encryptedPwd);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());

        return save(user);
    }

    @Override
    public String login(UserLoginDTO loginDTO, String loginIp) {
        // 初始化登录日志对象（无论成功失败都记录）
        LoginLog loginLog = new LoginLog();
        loginLog.setLoginIp(loginIp); // 设置登录IP
        loginLog.setLoginTime(LocalDateTime.now()); // 设置登录时间

        try {
            // 1. 查询用户
            User user = getByUsername(loginDTO.getUsername());
            if (user == null) {
                // 登录失败：用户名不存在
                loginLog.setLoginStatus(0); // 0=失败
                recordLoginLog(loginLog); // 记录失败日志
                throw new UserAuthException("用户名或密码错误");
            }

            // 2. 密码校验
            boolean matches = passwordEncoder.matches(loginDTO.getPassword(), user.getPassword());
            if (!matches) {
                // 登录失败：密码错误
                loginLog.setUserId(user.getId()); // 记录失败的用户ID（如果用户存在）
                loginLog.setLoginStatus(0);
                recordLoginLog(loginLog); // 记录失败日志
                throw new UserAuthException("用户名或密码错误");
            }

            // 3. 登录成功：记录日志
            loginLog.setUserId(user.getId()); // 关联成功登录的用户ID
            loginLog.setLoginStatus(1); // 1=成功
            recordLoginLog(loginLog); // 记录成功日志

            // 4. 生成 JWT 令牌
            return jwtUtil.generateToken(user.getId(),user.getRole());
        } catch (UserAuthException e) {
            // 捕获自定义异常，已在上面记录日志，直接抛出
            throw e;
        } catch (Exception e) {
            // 其他异常（如数据库异常），记录失败日志
            loginLog.setLoginStatus(0);
            recordLoginLog(loginLog);
            throw new UserAuthException("登录失败，请重试");
        }
    }

    @Override
    public User getByUsername(String username) {
        if (!StringUtils.hasText(username)) {
            return null;
        }
        return getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
    }

    @Override
    public UserInfoDTO getUserInfo(Long userId) {
        User user = getById(userId);
        if (user == null) {
            throw new UserAuthException("用户不存在");
        }
        UserInfoDTO infoDTO = new UserInfoDTO();
        BeanUtils.copyProperties(user, infoDTO);
        return infoDTO;
    }

    @Override
    public boolean updateUserInfo(Long userId, UserInfoDTO infoDTO) {
        User user = new User();
        user.setId(userId);
        BeanUtils.copyProperties(infoDTO, user);
        user.setUpdateTime(LocalDateTime.now());
        user.setAvatar(infoDTO.getAvatar());  // 头像URL
        return updateById(user);
    }

    @Override
    public void recordLoginLog(LoginLog loginLog) {
        loginLogMapper.insert(loginLog); // 插入日志到数据库
    }

    @Override
    public boolean existsById(Long userId) {
        return baseMapper.selectById(userId)==null;
    }

    @Override
    public void recordClickBehavior(Long userId, Long goodsId) {
        UserBehavior behavior = new UserBehavior();
        behavior.setUserId(userId);
        behavior.setGoodsId(goodsId);
        behavior.setBehaviorType("CLICK");
        userBehaviorMapper.insert(behavior);
    }

    @Override
    public boolean recordFavoriteBehavior(Long userId, Long goodsId) {
        // 检查是否已收藏（通过唯一索引避免重复）
        LambdaQueryWrapper<UserBehavior> query = new LambdaQueryWrapper<UserBehavior>()
                .eq(UserBehavior::getUserId, userId)
                .eq(UserBehavior::getGoodsId, goodsId)
                .eq(UserBehavior::getBehaviorType, "FAVORITE");

        UserBehavior existing = userBehaviorMapper.selectOne(query);
        if (existing != null) {
            return false;  // 已收藏，返回失败
        }

        // 插入收藏记录
        UserBehavior behavior = new UserBehavior();
        behavior.setUserId(userId);
        behavior.setGoodsId(goodsId);
        behavior.setBehaviorType("FAVORITE");
        userBehaviorMapper.insert(behavior);
        return true;
    }

    @Override
    public boolean cancelFavoriteBehavior(Long userId, Long goodsId) {
        int rows = userBehaviorMapper.delete(new LambdaQueryWrapper<UserBehavior>()
                .eq(UserBehavior::getUserId, userId)
                .eq(UserBehavior::getGoodsId, goodsId)
                .eq(UserBehavior::getBehaviorType, "FAVORITE"));
        return rows > 0;  // 删除成功返回true
    }

    @Override
    public List<UserBehavior> getUserBehaviors(Long userId) {
        return userBehaviorMapper.selectList(new LambdaQueryWrapper<UserBehavior>()
                .eq(UserBehavior::getUserId, userId)
                .orderByDesc(UserBehavior::getCreateTime));
    }
    /**
     * 超级管理员修改用户角色（仅SUPER_ADMIN可调用）
     * @param userId 目标用户ID
     * @param newRole 新角色（USER/ADMIN/SUPER_ADMIN）
     * @return 是否修改成功
     */
    @Override
    @Transactional // 确保更新操作原子性
    public boolean updateUserRole(Long userId, String newRole) {
        // 1. 校验角色合法性（只能是预设的三种角色）
        if (!"USER".equals(newRole) && !"ADMIN".equals(newRole) && !"SUPER_ADMIN".equals(newRole)) {
            throw new IllegalArgumentException("角色必须是 USER、ADMIN 或 SUPER_ADMIN");
        }

        // 2. 校验目标用户是否存在
        User user = baseMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 3. 避免重复更新（角色未变化时直接返回成功）
        if (newRole.equals(user.getRole())) {
            return true;
        }

        // 4. 更新用户角色
        user.setRole(newRole);
        int rows = baseMapper.updateById(user);
        return rows > 0; // 受影响行数>0表示更新成功
    }

    @Override
    @Transactional
    public boolean changePassword(Long userId, PasswordDTO passwordDTO) {
        User user = baseMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 2. 验证旧密码
        if (!passwordEncoder.matches(passwordDTO.getOldPassword(), user.getPassword())) {
            throw new RuntimeException("旧密码错误");
        }

        // 3. 加密新密码并更新
        user.setPassword(passwordEncoder.encode(passwordDTO.getNewPassword()));
        return baseMapper.updateById(user) > 0;
    }

    @Override
    @Transactional
    public boolean createMerchant(UserRegisterDTO registerDTO) {
        if (getByUsername(registerDTO.getUsername()) != null) {
            throw new RuntimeException("用户名已存在");
        }
        // 2. 创建商家账号（角色固定为MERCHANT）
        User merchant = new User();
        BeanUtils.copyProperties(registerDTO, merchant);
        merchant.setPassword(passwordEncoder.encode(registerDTO.getPassword()));
        merchant.setRole("MERCHANT");  // 强制设置为商家角色
        merchant.setCreateTime(LocalDateTime.now());
        return baseMapper.insert(merchant) > 0;
    }
}
